package org.example.erat.util;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.erat.entity.Experiment;
import org.example.erat.entity.Report;
import org.example.erat.entity.Student;
import org.example.erat.repository.ExperimentRepository;
import org.example.erat.repository.ReportRepository;
import org.example.erat.repository.StudentRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 报告数据初始化器
 * 用于在应用启动时初始化一些示例报告数据
 */
@Component
@RequiredArgsConstructor
@Order(3) // 在其他数据初始化之后执行
@Slf4j
public class ReportDataInitializer implements CommandLineRunner {

    private final StudentRepository studentRepository;
    private final ExperimentRepository experimentRepository;
    private final ReportRepository reportRepository;

    @Override
    @Transactional
    public void run(String... args) {
        log.info("开始初始化报告数据...");

        // 检查是否已有报告数据
        if (reportRepository.count() > 0) {
            log.info("报告数据已存在，跳过初始化");
            return;
        }

        // 初始化数据结构课程（课程ID=1）的学生（班级ID=1）的报告数据
        initializeReportsForCourseAndClass(1L, 1L);

        // 初始化软件工程课程（课程ID=2）的学生（班级ID=2）的报告数据
        initializeReportsForCourseAndClass(2L, 2L);

        // 初始化机器学习课程（课程ID=3）的学生（班级ID=3）的报告数据
        initializeReportsForCourseAndClass(3L, 3L);

        log.info("报告数据初始化完成");
    }

    /**
     * 为指定课程和班级初始化报告数据
     * @param courseId 课程ID
     * @param classId 班级ID
     */
    private void initializeReportsForCourseAndClass(Long courseId, Long classId) {
        log.info("初始化课程ID={}，班级ID={}的报告数据", courseId, classId);

        // 获取班级学生
        List<Student> students = studentRepository.findByClassEntityId(classId);
        if (students.isEmpty()) {
            log.warn("班级ID={}没有学生", classId);
            return;
        }

        // 获取课程实验
        List<Experiment> experiments = experimentRepository.findByCourseId(courseId);
        if (experiments.isEmpty()) {
            log.warn("课程ID={}没有实验", courseId);
            return;
        }

        // 为每个实验创建报告
        for (Experiment experiment : experiments) {
            // 根据实验编号选择不同的学生提交报告
            List<Student> submittingStudents = selectSubmittingStudents(students, experiment.getExperimentNumber());

            for (Student student : submittingStudents) {
                // 检查是否已存在报告
                Optional<Report> existingReport = reportRepository.findByStudentAndExperiment(student, experiment);
                if (existingReport.isPresent()) {
                    log.info("学生{}的实验{}报告已存在", student.getName(), experiment.getName());
                    continue;
                }

                // 创建报告文件路径
                String courseName = experiment.getCourse().getName();
                String className = student.getClassEntity().getName();
                String experimentName = experiment.getName();
                String fileName = experimentName + "_" + student.getStudentId() + "_" + student.getName() + ".doc";
                String filePath = "D:/reports/" + courseName + "/" + className + "/" + experimentName + "/" + fileName;

                // 创建报告记录
                Report report = Report.builder()
                        .fileName(fileName)
                        .filePath(filePath)
                        .submissionTime(LocalDateTime.now())
                        .student(student)
                        .experiment(experiment)
                        .build();

                reportRepository.save(report);
                log.info("创建报告: {}", fileName);
            }
        }
    }

    /**
     * 根据实验编号选择提交报告的学生
     * @param students 学生列表
     * @param experimentNumber 实验编号
     * @return 提交报告的学生列表
     */
    private List<Student> selectSubmittingStudents(List<Student> students, Integer experimentNumber) {
        // 根据实验编号和一些规则选择不同的学生
        // 这里简单地根据实验编号和学生ID的奇偶性来选择
        return students.stream()
                .filter(student -> {
                    Long studentId = student.getId();

                    // 实验1：学号为偶数的学生提交
                    if (experimentNumber == 1) {
                        return studentId % 2 == 0;
                    }

                    // 实验2：学号为奇数的学生提交
                    if (experimentNumber == 2) {
                        return studentId % 2 == 1;
                    }

                    // 实验3：学号能被3整除的学生提交
                    if (experimentNumber == 3) {
                        return studentId % 3 == 0;
                    }

                    // 实验4：学号能被3余1的学生提交
                    if (experimentNumber == 4) {
                        return studentId % 3 == 1;
                    }

                    // 实验5：学号能被3余2的学生提交
                    if (experimentNumber == 5) {
                        return studentId % 3 == 2;
                    }

                    // 其他实验：随机选择（这里用学号与实验编号的和的奇偶性来决定）
                    return (studentId + experimentNumber) % 2 == 0;
                })
                .collect(Collectors.toList());
    }
}
